﻿using Medallion.Threading;
using Medallion.Threading.Redis;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Caching.StackExchangeRedis;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.OpenApi.Models;
using Qianke.Core.Common;
using Qianke.Core.Saas.WebApi.SaasExtensions;
using Qianke.Core.Saas.WebApi.SaasExtensions.SaasAuditing;
using Qianke.Core.Saas.WebApi.SaasExtensions.SaasFilters;
using StackExchange.Redis;
using System.Diagnostics;
using Volo.Abp;
using Volo.Abp.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Mvc.ExceptionHandling;
using Volo.Abp.Auditing;
using Volo.Abp.Autofac;
using Volo.Abp.Caching.StackExchangeRedis;
using Volo.Abp.DistributedLocking;
using Volo.Abp.Http;
using Volo.Abp.Json.Newtonsoft;
using Volo.Abp.Modularity;
using Volo.Abp.Swashbuckle;
using Volo.Abp.Uow;

namespace Qianke.Core.Saas.WebApi
{
    [DependsOn(
        typeof(AbpAutofacModule),
        typeof(AbpUnitOfWorkModule),
        typeof(AbpAspNetCoreMvcModule),
        typeof(AbpSwashbuckleModule),
        typeof(QiankeCommonModule),
        typeof(AbpCachingStackExchangeRedisModule),
        typeof(AbpDistributedLockingModule),
        typeof(AbpJsonNewtonsoftModule)
        )]
    public class QiankeCoreSaasWebApiModule : AbpModule
    {

        public override void PreConfigureServices(ServiceConfigurationContext context)
        {
            var services = context.Services;
            HttpMethodHelper.ConventionalPrefixes = new Dictionary<string, string[]>();

            //配置JSON格式
            services.AddNewtonsoftJosn();
            //禁用.netcore default的ModelState验证
            services.EnableNetCoreModelStateInvalid();
        }

        public override void ConfigureServices(ServiceConfigurationContext context)
        {
            var services = context.Services;
            var configurantion = services.GetConfiguration();

            //配置SAAS项目专用 认证机制
            services.AddSaasAuthentication();

            services.AddLogging(logginBuilder =>
            {
                logginBuilder.AddConsole();
                logginBuilder.SetMinimumLevel(LogLevel.Trace);
            });

            Configure<AbpUnitOfWorkOptions>(options =>
            {
                options.Timeout = 30; // 设置超时时间
            });

            services.AddCors(options =>
            {
                options.AddDefaultPolicy(builder =>
                {
                    builder
                        .AllowAnyOrigin()
                        .AllowAnyMethod() // 允许任何方法（GET, POST, 等）
                        .AllowAnyHeader() // 允许任何头
                        ; // 允许凭证
                });
            });






            services.AddStackExchangeRedisCache(options =>
            {
                configurantion.GetSection(nameof(RedisCacheOptions)).Bind(options);
                if (string.IsNullOrEmpty(options.Configuration))
                    options.Configuration = "redis.ip239.com:6379,defaultDatabase=1,password=huileyou@123";
            });

            var configuration = context.Services.GetConfiguration();
            context.Services.AddSingleton<IDistributedLockProvider>(sp =>
            {
                var connection = ConnectionMultiplexer.Connect(configuration["RedisLockOptions:Configuration"]);
                return new RedisDistributedSynchronizationProvider(connection.GetDatabase(0));
            });
            Configure<AbpDistributedLockOptions>(options =>
            {
                options.KeyPrefix = "Saas:Order:Lock:";
            });


            //绑定日志配置
            services.ConfigureFromConfiguration<AbpAuditingOptions>(options =>
            {
                options.IsEnabledForAnonymousUsers = true; // 允许匿名访问
                options.IsEnabled = true; // 启用审计功能
                options.DisableLogActionInfo = true;
            });

            services.ConfigureFromConfiguration<SaasAuditingOptions>();
            Configure<MvcOptions>(options =>
            {
                var p = options.Filters.Where(u =>
                {
                    var fiter = u as ServiceFilterAttribute;
                    if (fiter == null) return false;
                    return fiter.ServiceType == typeof(AbpExceptionFilter) || fiter.ServiceType == typeof(AbpExceptionPageFilter) ;
                }).ToList();
                if (p.Count > 0)
                    p.ForEach(U => options.Filters.Remove(U));
                //添加我们自己的过滤器
                options.Filters.Add(typeof(SaasAsyncActionFilter), -2);

                // 找到 JSON 输入格式化器
                var jsonInputFormatter = options.InputFormatters
                    .OfType<Microsoft.AspNetCore.Mvc.Formatters.SystemTextJsonInputFormatter>()
                    .FirstOrDefault();
                if (jsonInputFormatter != null)
                {
                    // 添加 text/html 支持的媒体类型
                    jsonInputFormatter.SupportedMediaTypes.Add("text/html");
                    jsonInputFormatter.SupportedMediaTypes.Add("application/x-www-form-urlencoded");
                }
            });
        }

        public override void PostConfigureServices(ServiceConfigurationContext context)
        {
            context.Services.AddYiSwaggerGen<QiankeCoreSaasWebApiModule>(options =>
            {
                options.SwaggerDoc("default",
                    new OpenApiInfo { Title = "BingYing.SystemModule.WebApi", Version = "v1", Description = "冰鹰测试项目" });
            });
            base.PostConfigureServices(context);
        }

        public override void OnApplicationInitialization(Volo.Abp.ApplicationInitializationContext context)
        {
            var app = context.GetApplicationBuilder();
            var env = context.GetEnvironment();

            app.UseCors();
            if (env.IsDevelopment())
                app.UseYiSwagger();

            app.UseStaticFiles(new StaticFileOptions()
            {
                OnPrepareResponse = ctx =>
                {
                    if (ctx.File.Name == "index.html")
                    {
                        // 设置缓存时间为 0，禁用缓存
                        ctx.Context.Response.Headers.Append("Cache-Control", "no-cache, no-store, must-revalidate");
                        ctx.Context.Response.Headers.Append("Pragma", "no-cache");
                        ctx.Context.Response.Headers.Append("Expires", "0");
                    }
                }
            });
            app.UseAuditing();
            app.UseAuthentication();
            app.UseAuthorization();
            //app.UseUnitOfWork();
        }



    }
}
